package com.ruoyi.warning.service.impl;

import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.deviceControl.domain.DeviceControl;
import com.ruoyi.deviceControl.dto.LinkageControlDto;
import com.ruoyi.deviceControl.service.IDeviceControlService;
import com.ruoyi.deviceControl.service.ILinkageControlService;
import com.ruoyi.system.domain.dto.GradedAlarmDto;
import com.ruoyi.warning.service.IAlarmLinkageControlService;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.identity.AnonymousProvider;
import org.eclipse.milo.opcua.sdk.client.api.identity.IdentityProvider;
import org.eclipse.milo.opcua.sdk.client.api.identity.UsernameProvider;
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
import org.eclipse.milo.opcua.stack.core.types.builtin.*;
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.function.Function;

@Service
public class AlarmLinkageControlServiceImpl implements IAlarmLinkageControlService {

    private final static String beltPointUrl = "opc.tcp://127.0.0.1:49320";//皮带
    private final static String otherPointUrl = "opc.tcp://127.0.0.1:49320";//其他
    private final static String monkeyCarPointUrl = "opc.tcp://127.0.0.1:49320";//猴车

    @Autowired
    private ILinkageControlService linkageControlService;

    @Autowired
    private IDeviceControlService deviceControlService;

    @Override
    public void writeNodeValueByLinkageControl(GradedAlarmDto gradedAlarmDto) {
        String pointUrl = null;
        List<LinkageControlDto> linkageControlDtos = linkageControlService.selectLinkageControlListByAlarmId(gradedAlarmDto.getGradedAlarmId());
        if (linkageControlDtos != null){
            for (LinkageControlDto linkageControlDto : linkageControlDtos) {
                DeviceControl deviceControl = deviceControlService.selectDeviceControlByDeviceControlId(linkageControlDto.getDeviceId());
                switch (deviceControl.getDeviceType()){
                    case "0":
                        pointUrl = beltPointUrl;
                        break;
                    case "1":
                        pointUrl = monkeyCarPointUrl;
                        break;
                    case "100":
                        pointUrl = otherPointUrl;
                        break;
                    default:
                        break;
                }
                OpcUaClient client =createClientNewEndpoint(pointUrl, "ua", "123456");
                //节点          煤矿1.皮带*.tag_name              煤矿.*.*     煤矿2.*.*
                NodeId nodeId = new NodeId(2, deviceControl.getTagName());
                //创建数据对象,此处的数据对象一定要定义类型，不然会出现类型错误，导致无法写入
                DataValue nowValue = new DataValue(new Variant(deviceControl.getTagValue()), null, null);
                //写入节点数据
                StatusCode statusCode = client.writeValue(nodeId, nowValue).join();
                System.out.println("结果：" + statusCode.isGood());
                // 延迟执行指令
                try {
                    Thread.sleep(Integer.parseInt(linkageControlDto.getDelayTime()) * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static OpcUaClient createClientNewEndpoint(String endPointUrl, String username, String password) {
        System.out.println(endPointUrl);
        IdentityProvider identityProvider = new AnonymousProvider();
        if (!StringUtils.isEmpty(username) || !StringUtils.isEmpty(password)) {
            identityProvider = new UsernameProvider(username, password);
        }
        try {
            Function<List<EndpointDescription>, Optional<EndpointDescription>> selectEndpoint = endpoints -> {
                final Optional<EndpointDescription> endpoint = endpoints
                        .stream()
                        //SecurityPolicy.Basic256
                        .filter(e -> e.getSecurityPolicyUri().equals(SecurityPolicy.None.getUri()))
                        .findFirst();
                EndpointDescription newEndpoint = new EndpointDescription(endPointUrl, endpoint.get().getServer(), endpoint.get().getServerCertificate(),
                        endpoint.get().getSecurityMode(), endpoint.get().getSecurityPolicyUri(), endpoint.get().getUserIdentityTokens(),
                        endpoint.get().getTransportProfileUri(), endpoint.get().getSecurityLevel());
                return Optional.of(newEndpoint);
            };
            IdentityProvider finalIdentityProvider = identityProvider;
            OpcUaClient opcClient = OpcUaClient.create(endPointUrl,
                    selectEndpoint,
                    configBuilder -> configBuilder
                            .setApplicationName(LocalizedText.english("plc"))
                            .setApplicationUri("urn:eclipse:milo:examples:client")
                            //访问方式
                            .setIdentityProvider(finalIdentityProvider)
                            .setRequestTimeout(UInteger.valueOf(10000))
                            .build()
            );
            opcClient.connect().get();
            System.out.println("连接成功:success");
            return opcClient;
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("======== opc connection fail ========");
        }
        return null;
    }
}
